package com.yami.shop.api.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.bean.enums.*;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.vo.OrderItemVO;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.config.ShopConfig;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import com.yami.shop.common.util.BeanUtil;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LGH
 */
@RestController
@RequestMapping("/p/myOrder")
@Tag(name = "我的订单接口")
@AllArgsConstructor
public class MyOrderController {

    private final OrderService orderService;

    private final ProductService productService;

    private final SkuService skuService;

    private final ShopConfig shopConfig;

    private final MyOrderService myOrderService;

    private final OrderItemService orderItemService;

    private final OrderRefundService orderRefundService;

    private final OrderVirtualInfoService orderVirtualInfoService;

    @GetMapping("/orderDetail")
    @Operation(summary =  "订单详情信息", description = "根据订单号获取订单详情信息")
    @Parameter(name = "orderNumbers", description = "订单号（多个订单以，相隔）" , required = true)
    public ServerResponseEntity<OrderShopDto> orderDetail(@RequestParam(name="orderNumber") String orderNumber) {
        String userId = SecurityUtils.getUser().getUserId();
        Long stationId = SecurityUtils.getUser().getStationId();
        OrderShopDto orderShopDto = orderService.orderDetail(orderNumber, userId, stationId);

        if (Objects.isNull(orderShopDto)) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        // 插入退款和虚拟商品信息
        refundAndVirtualInfo(orderShopDto, stationId);
        return ServerResponseEntity.success(orderShopDto);
    }

    /**
     * 添加下虚拟商品的信息
     *
     * @param order        订单信息
     * @param orderShopDto 用于前端展示的订单信息
     * @param stationId 门店id
     */
    private void handlerVirtualProdOrder(Order order, OrderShopDto orderShopDto,Long stationId) {
        orderShopDto.setOrderMold(order.getOrderMold());
        // 虚拟商品留言信息
        orderShopDto.setVirtualRemark(order.getVirtualRemark());
        orderShopDto.setWriteOffStart(order.getWriteOffStart());
        orderShopDto.setWriteOffEnd(order.getWriteOffEnd());
        orderShopDto.setWriteOffNum(order.getWriteOffNum());
        orderShopDto.setWriteOffMultipleCount(order.getWriteOffMultipleCount());
        if (Objects.equals(order.getIsRefund(), 0)) {
            orderShopDto.setCanAllRefund(false);
            orderShopDto.setCanRefund(false);
        }

        // 卡券信息
        List<OrderVirtualInfo> virtualInfoList = orderVirtualInfoService.list(new LambdaQueryWrapper<OrderVirtualInfo>()
                .eq(OrderVirtualInfo::getOrderNumber, order.getOrderNumber())
                .eq(Objects.nonNull(stationId),OrderVirtualInfo::getIsWriteOff, 1)
                .eq(Objects.nonNull(stationId),OrderVirtualInfo::getStationId, stationId));
        boolean flag = Objects.equals(order.getStatus(), OrderStatus.WAIT_GROUP.value()) || Objects.equals(order.getStatus(), OrderStatus.UNPAY.value()) ;
        if (CollectionUtil.isNotEmpty(virtualInfoList) && !flag) {
            orderShopDto.setVirtualInfoList(virtualInfoList);
            orderShopDto.setTotalNum(virtualInfoList.size());
        }
    }

    @GetMapping("/myNewOrder")
    @Operation(summary = "订单列表信息" , description = "根据订单状态获取订单列表信息，状态为0时获取所有订单")
    public ServerResponseEntity<IPage<MyNewOrderDto>> myNewOrder(PageParam<MyNewOrderDto> page,Long shopId) {
        String userId = SecurityUtils.getUser().getUserId();
        IPage<MyNewOrderDto> myOrderDtoIpage = myOrderService.pageMyOrderByUserIdAndSuccess(page, userId,shopId);
        return ServerResponseEntity.success(myOrderDtoIpage);
    }


    @GetMapping("/myOrder")
    @Operation(summary = "订单列表信息" , description = "根据订单状态获取订单列表信息，状态为0时获取所有订单")
    @Parameter(name = "status", description = "订单状态 1:待付款 2:待发货 3:待收货 4:待评价 5:成功 6:失败 7待成团" )
    public ServerResponseEntity<IPage<MyOrderDto>> myOrder(@RequestParam(value = "status") Integer status, @RequestParam(value = "prodName", required = false ) String prodName, PageParam<MyOrderDto> page) {
        String userId = SecurityUtils.getUser().getUserId();
        IPage<MyOrderDto> myOrderDtoIpage = myOrderService.pageMyOrderByUserIdAndStatus(page, userId, status, prodName);
        return ServerResponseEntity.success(myOrderDtoIpage);
    }

    @GetMapping("/myOrderSearch")
    @Operation(summary =  "订单列表信息查询", description = "根据订单编号或者订单中商品名称搜索")
    @Parameters({
            @Parameter(name = "status", description = "订单状态 1:待付款 2:待发货 3:待收货 4:待评价 5:成功 6:失败"),
            @Parameter(name = "orderMold", description = "订单类别 0.实物商品订单 1. 虚拟商品订单"),
            @Parameter(name = "orderName", description = "订单编号或者订单中商品名称"),
            @Parameter(name = "orderTimeStatus", description = "0全部订单 1最近七天 2最近三个月 3三个月之前 订单"),
            @Parameter(name = "orderType", description = "0全部订单 1拼团订单 2秒杀订单 3积分订单"),
            @Parameter(name = "orderNumber", description = "订单编号"),
            @Parameter(name = "shopId", description = "店铺id")
    })
    public ServerResponseEntity<IPage<MyOrderDto>> myOrderSearch(@RequestParam(name="status") Integer status,
                                                           @RequestParam(name="orderName") String orderName,
                                                           @RequestParam(name="orderTimeStatus", required = false) Integer orderTimeStatus,
                                                           @RequestParam(name="orderType", required = false) Integer orderType,
                                                           @RequestParam(name="orderMold") Integer orderMold,
                                                           @RequestParam(name="orderNumber") String orderNumber,
                                                           @RequestParam(name="shopId", required = false) Long shopId,
                                                           PageParam<MyOrderDto> page) {
        String userId = SecurityUtils.getUser().getUserId();
        IPage<MyOrderDto> myOrderDtoIpage = myOrderService.pageMyOrderByParams(page, userId, status, orderName, orderTimeStatus, orderType, orderNumber, shopId,orderMold);
        return ServerResponseEntity.success(myOrderDtoIpage);
    }

    @GetMapping("/getOrderItem")
    @Operation(summary =  "获取订单项信息", description = "根据订单项Id获取订单项信息")
    @Parameter(name = "orderItemId", description = "订单项Id")
    public ServerResponseEntity<OrderItemVO> getOrderItem(@RequestParam(name="orderItemId") Long orderItemId) {
        String imgDomainName = shopConfig.getDomain().getResourcesDomainName();
        OrderItem orderItem = orderItemService.getByIdI18n(orderItemId);
        orderItem.setPic((orderItem.getPic() != null&&!orderItem.getPic().startsWith("http://")&&!orderItem.getPic().startsWith("https://"))? imgDomainName + "/" + orderItem.getPic() : orderItem.getPic());
        Order one = orderService.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNumber,orderItem.getOrderNumber()));
        OrderItemVO orderItemVO = BeanUtil.map(orderItem, OrderItemVO.class);
        orderItemVO.setPayDate(one.getPayTime());
        return ServerResponseEntity.success(orderItemVO);
    }

    @GetMapping("/getOrderItems")
    @Operation(summary =  "获取订单项信息", description = "根据订单编号orderNumber获取订单项信息")
    @Parameter(name = "orderNumber", description = "订单编号")
    public ServerResponseEntity<List<OrderItem>> getOrderItems(@RequestParam(name="orderNumber") String orderNumber) {
        String imgDomainName = shopConfig.getDomain().getResourcesDomainName();
        List<OrderItem> orderItems = orderItemService.listAndPayTimeByOrderNumber(orderNumber);
        for (OrderItem orderItem : orderItems) {
            orderItem.setPic((orderItem.getPic() != null&&!orderItem.getPic().startsWith("http://")&&!orderItem.getPic().startsWith("https://"))? imgDomainName + "/" + orderItem.getPic() : orderItem.getPic());
        }
        return ServerResponseEntity.success(orderItems);
    }

    @GetMapping("/myOrderComment")
    @Operation(summary =  "订单评价列表接口", description = "根据订单评价状态获取订单列表信息")
    @Parameter(name = "commStatus", description = "订单状态 0:待评价 1已评价")
    public ServerResponseEntity<IPage<MyOrderDto>> myOrderComment(PageParam<MyOrderDto> page) {
        String userId = SecurityUtils.getUser().getUserId();
        IPage<MyOrderDto>  myOrderDtoIpage = myOrderService.myOrderComment(page, userId);
        return ServerResponseEntity.success(myOrderDtoIpage);
    }

    @GetMapping("/myOrderItemsComment")
    @Operation(summary =  "订单项评价列表接口", description = "根据订单评价状态获取订单列表信息")
    @Parameter(name = "commStatus", description = "订单状态 0:待评价 1已评价")
    public ServerResponseEntity<IPage<MyOrderItemDto>> myOrderItemsComment(@RequestParam(name="commStatus") Integer commStatus,
                                                                     PageParam<MyOrderItemDto> page) {
        String userId = SecurityUtils.getUser().getUserId();
        IPage<MyOrderItemDto> myOrderDtoIpage = myOrderService.myOrderItemsComment(page, userId, commStatus);
        return ServerResponseEntity.success(myOrderDtoIpage);
    }

    @GetMapping("/cancel/{orderNumber}")
    @Operation(summary =  "根据订单编号取消订单", description = "根据订单编号取消订单")
    @Parameter(name = "orderNumber", description = "订单编号", required = true)
    public ServerResponseEntity<String> cancel(@PathVariable("orderNumber") String orderNumber) {
        String userId = SecurityUtils.getUser().getUserId();
        Order order = orderService.getOrderByOrderNumberAndUserId(orderNumber, userId, true);
        // 如果订单过期 直接返回
        if (Objects.equals(order.getStatus(), OrderStatus.CLOSE.value())) {
            return ServerResponseEntity.success();
        }
        if (!Objects.equals(order.getStatus(), OrderStatus.UNPAY.value())) {
            // 订单已支付，无法取消订单
            throw new YamiShopBindException("yami.order.status.change");
        }

        List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
        order.setOrderItems(orderItems);
        // 取消订单
        orderService.cancelOrders(Collections.singletonList(order));
        // 清除缓存
        for (OrderItem orderItem : orderItems) {
            productService.removeProdCacheByProdId(orderItem.getProdId());
            skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId());
        }
        return ServerResponseEntity.success();
    }

    @PutMapping("/receipt/{orderNumber}")
    @Operation(summary =  "根据订单号确认收货", description = "根据订单号确认收货")
    @Parameter(name = "orderNumber", description = "订单编号", required = true)
    public ServerResponseEntity<String> receipt(@PathVariable("orderNumber") String orderNumber) {
        String userId = SecurityUtils.getUser().getUserId();
        Order order = orderService.getOrderByOrderNumberAndUserId(orderNumber, userId, true);

        if (!Objects.equals(order.getStatus(), OrderStatus.CONSIGNMENT.value())) {
            // 订单不处于待收货状态，无法确认收货
            throw new YamiShopBindException("yami.order.no.delivery");
        }
        if (Objects.equals(order.getRefundStatus(), RefundStatusEnum.APPLY.value())) {
            // 订单退款中，无法确认收货
            throw new YamiShopBindException("yami.order.receipt.refund");
        }
        List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
        order.setOrderItems(orderItems);
        // 确认收货
        orderService.receiptOrder(Collections.singletonList(order));

        for (OrderItem orderItem : orderItems) {
            productService.removeProdCacheByProdId(orderItem.getProdId());
            skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId());
        }
        return ServerResponseEntity.success();
    }

    @DeleteMapping("/{orderNumber}")
    @Operation(summary =  "根据订单号删除订单", description = "根据订单号删除订单")
    @Parameter(name = "orderNumber", description = "订单号", required = true)
    public ServerResponseEntity<String> delete(@PathVariable("orderNumber") String orderNumber) {
        String userId = SecurityUtils.getUser().getUserId();
        Order order = orderService.getOrderByOrderNumberAndUserId(orderNumber, userId, true);
        if (!Objects.equals(order.getStatus(), OrderStatus.SUCCESS.value()) && !Objects.equals(order.getStatus(), OrderStatus.CLOSE.value())) {
            // 订单未完成或未关闭，无法删除订单
            throw new YamiShopBindException("yami.order.no.success");
        }
        // 删除订单
        orderService.deleteOrders(Collections.singletonList(order));
        // 删除成功
        return ServerResponseEntity.success(I18nMessage.getMessage("yami.delete.successfully"));
    }

    @GetMapping("/getOrderStatus")
    @Operation(summary =  "根据订单编号获取订单状态")
    public ServerResponseEntity<OrderShopDto> getOrderStatus(@RequestParam("orderNumber") String orderNumber) {
        Order order = orderService.getOrderByOrderNumber(orderNumber);
        OrderShopDto orderShopDto = new OrderShopDto();
        orderShopDto.setStatus(order.getStatus());
        orderShopDto.setRefundStatus(order.getRefundStatus());
        // 如果是虚拟商品订单，处理下虚拟商品订单相关数据
        if(Objects.equals(order.getOrderMold(),1)) {
            Long stationId = SecurityUtils.getUser().getStationId();
            orderShopDto.setOrderMold(order.getOrderMold());
            // 虚拟商品留言信息
            orderShopDto.setVirtualRemark(order.getVirtualRemark());
            orderShopDto.setWriteOffStart(order.getWriteOffStart());
            orderShopDto.setWriteOffEnd(order.getWriteOffEnd());
            orderShopDto.setWriteOffNum(order.getWriteOffNum());
            orderShopDto.setWriteOffMultipleCount(order.getWriteOffMultipleCount());
            handlerVirtualProdOrder(orderShopDto, order.getIsRefund(), order.getStatus(), order.getOrderNumber(), stationId);
        }
        return ServerResponseEntity.success(orderShopDto);
    }
    /**
     * 插入订单项、退款和虚拟商品的数据
     * @param orderShopDto
     * @param stationId
     */
    private void refundAndVirtualInfo(OrderShopDto orderShopDto, Long stationId) {
        // 查询商品的信息，用于获取商品秒杀id
        // 查询第一个商品是否为秒杀商品
        if (Objects.equals(orderShopDto.getOrderType(), OrderType.SECKILL.value())) {
            Product product = productService.getById(orderShopDto.getOrderItemDtos().get(0).getProdId());
            orderShopDto.setSeckillId(product.getActivityId());
        }

        // 查询订单退款信息
        List<Integer> returnMoneyStsList = new ArrayList<>();
        returnMoneyStsList.add(ReturnMoneyStsType.FAIL.value());
        returnMoneyStsList.add(ReturnMoneyStsType.CANCEL.value());
        returnMoneyStsList.add(ReturnMoneyStsType.REJECT.value());
        List<OrderRefund> orderRefunds = orderRefundService.list(new LambdaQueryWrapper<OrderRefund>()
                .eq(OrderRefund::getOrderId, orderShopDto.getOrderId())
                .notIn(OrderRefund::getReturnMoneySts, returnMoneyStsList)
        );
        Map<Long, List<OrderRefund>> refundMap = orderRefunds.stream().collect(Collectors.groupingBy(OrderRefund::getOrderId));

        Order order = new Order();
        order.setStatus(orderShopDto.getStatus());
        order.setFinallyTime(orderShopDto.getFianllyTime());
        double alreadyRefundAmount = 0.0;
        // 可以退款的状态(订单已支付，且未关闭)，并在退款时间内
        if (orderShopDto.getStatus() > OrderStatus.UNPAY.value() && orderShopDto.getStatus() < OrderStatus.CLOSE.value() && orderRefundService.checkRefundDate(order)) {
            orderShopDto.setCanRefund(true);
            // 有没有正在退款中的订单
            if (CollectionUtil.isEmpty(orderRefunds)) {
                orderShopDto.setCanAllRefund(true);
            }
        }
        if (refundMap.containsKey(orderShopDto.getOrderId())) {
            alreadyRefundAmount = handleOrderRefundInfo(refundMap.get(orderShopDto.getOrderId()), orderShopDto);
        }
        orderShopDto.setCanRefundAmount(Arith.sub(orderShopDto.getActualTotal(), alreadyRefundAmount));

        // 虚拟商品数据处理
        if(Objects.equals(orderShopDto.getOrderMold(),1)) {
            this.handlerVirtualProdOrder(orderShopDto, orderShopDto.getIsRefund(), orderShopDto.getStatus(), orderShopDto.getOrderNumber(), stationId);
        }

    }

    private double handleOrderRefundInfo(List<OrderRefund> orderRefunds, OrderShopDto orderShopDto) {
        double alreadyRefundAmount = 0D;
        for (OrderRefund orderRefund : orderRefunds) {
            alreadyRefundAmount = Arith.add(alreadyRefundAmount, orderRefund.getRefundAmount());
            // 整单退款
            if (Objects.equals(RefundType.ALL.value(), orderRefund.getRefundType())) {
                orderShopDto.setCanRefund(false);
                // 统一的退款单号
                for (OrderItemDto orderItemDto : orderShopDto.getOrderItemDtos()) {
                    orderItemDto.setRefundSn(orderRefund.getRefundSn());
                }
                break;
            }
            // 单项退款，每个单号都不一样
            for (OrderItemDto orderItemDto : orderShopDto.getOrderItemDtos()) {
                if (Objects.equals(orderItemDto.getOrderItemId(), orderRefund.getOrderItemId())) {
                    orderItemDto.setRefundSn(orderRefund.getRefundSn());
                }
            }
        }
        return alreadyRefundAmount;
    }


    /**
     * 添加下虚拟商品的信息
     *
     * @param orderShopDto 用于前端展示的订单信息
     * @param isRefund
     * @param status
     * @param orderNumber
     * @param stationId 门店id
     */
    private void handlerVirtualProdOrder(OrderShopDto orderShopDto, Integer isRefund, Integer status, String orderNumber,Long stationId) {
        if (Objects.equals(isRefund, 0)) {
            orderShopDto.setCanAllRefund(false);
            orderShopDto.setCanRefund(false);
        }

        boolean flag = Objects.equals(status, OrderStatus.WAIT_GROUP.value()) || Objects.equals(status, OrderStatus.UNPAY.value()) ;
        if (flag) {
            return;
        }
        // 卡券信息
        List<OrderVirtualInfo> virtualInfoList = orderVirtualInfoService.list(new LambdaQueryWrapper<OrderVirtualInfo>()
                .eq(OrderVirtualInfo::getOrderNumber, orderShopDto.getOrderNumber())
                .eq(Objects.nonNull(stationId), OrderVirtualInfo::getIsWriteOff, 1)
                .eq(Objects.nonNull(stationId), OrderVirtualInfo::getStationId, stationId));
        if (CollectionUtil.isNotEmpty(virtualInfoList)) {
            orderShopDto.setVirtualInfoList(virtualInfoList);
            orderShopDto.setTotalNum(virtualInfoList.size());
        }
    }
}
